package com.ruoyi.project.proxy;

import com.alibaba.fastjson.JSON;
import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType;
import com.github.xingshuangs.iot.protocol.s7.service.S7PLC;
import lombok.extern.slf4j.Slf4j;
import org.apache.plc4x.java.DefaultPlcDriverManager;
import org.apache.plc4x.java.api.PlcConnection;
import org.apache.plc4x.java.api.messages.PlcReadRequest;
import org.apache.plc4x.java.api.messages.PlcWriteRequest;
import org.apache.plc4x.java.api.messages.PlcWriteResponse;
import org.apache.plc4x.java.api.types.PlcResponseCode;
import org.apache.shiro.crypto.hash.Hash;
import org.eclipse.paho.client.mqttv3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.apache.plc4x.java.api.messages.PlcReadResponse;

import java.util.HashMap;
import java.util.concurrent.TimeUnit;

@Slf4j
//@Configuration
public class MqttProxyCallBack implements MqttCallback {

    private MqttClient client;
private MqttConnectOptions options;
    MqttProxyCallBack(MqttClient mqttClient,MqttConnectOptions mqttOptions) {
        this.client = mqttClient;
        this.options = mqttOptions;
    }

//    @Value("${spring.mqtt.client.id}")
//    private String clientId;
//    /**
//     * 与服务器断开的回调
//     */
//    @Override
//    public void connectionLost(Throwable cause) {
//        System.out.println(clientId+"与服务器断开连接");
//    }

    /**
     * 客户端断开连接的回调
     */
    @Override
    public void connectionLost(Throwable throwable) {
        System.out.println("与服务器断开连接，可重连");
//        System.out.println("MQTT连接断开，发起重连......");
//        try {
//            if (null != client && !client.isConnected()) {
//                client.reconnect();
//                System.out.println("尝试重新连接");
//                log.info("isconnected:{}",client.isConnected());
//            } else {
//                client.connect(options);
//                System.out.println("尝试建立新连接");
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }

    /**
     * 消息到达的回调
     */
    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {
        System.out.println(String.format("接收消息主题 : %s", topic));
        System.out.println(String.format("接收消息Qos : %d", message.getQos()));
        System.out.println(String.format("接收消息内容 : %s", new String(message.getPayload())));
        System.out.println(String.format("接收消息retained : %b", message.isRetained()));

        if (topic.startsWith("v1/devices/me/rpc/request/")) {
            String requestId = topic.replace("v1/devices/me/rpc/request/", "");
            String topic_send = "v1/devices/me/rpc/response/" + requestId;
            HashMap<String, String> dataMap = JSON.parseObject(message.getPayload(), HashMap.class);
            log.info(JSON.toJSONString(dataMap));
//            dataMap.put("params","59");
            String method = dataMap.get("method");
            String[] str = method.split(",");

            if (str[0].equals("get")) {

                String plctype = str[1];
                String ip = str[2];
                String address = str[3];
                String datatype = str[4];

                log.info("{} {} {} {}",plctype,ip,address,datatype);

//                String url = str[1];
//                String tagaddress = str[2];
//                try (PlcConnection connection = new DefaultPlcDriverManager().getConnection(url)) {
//                    final PlcReadRequest.Builder builder = connection.readRequestBuilder();
//                    builder.addTagAddress("tag1", tagaddress);
//                    final PlcReadRequest readRequest = builder.build();
//                    final PlcReadResponse readResponse = readRequest.execute().get(5, TimeUnit.SECONDS);
//                    String ret = readResponse.getString("tag1");
//                    client.publish(topic_send, ret.getBytes(), 1, false);
//                }catch (Exception e){
//                    client.publish(topic_send, "0".getBytes(), 1, false);
//                }

                String ret;
                //S200_SMART
                S7PLC s7 = new S7PLC(EPlcType.valueOf(plctype),ip);
                try {
                    if (datatype.equals("BOOL")) {
                        ret = String.valueOf(s7.readBoolean(address));
                    } else if (datatype.equals("BYTE")) {
                        ret = String.valueOf(s7.readByte(address));
                    } else if (datatype.equals("INT16")) {
                        ret = String.valueOf(s7.readInt16(address));
                    } else if (datatype.equals("UINT16")) {
                        ret = String.valueOf(s7.readUInt16(address));
                    } else if (datatype.equals("INT32")) {
                        ret = String.valueOf(s7.readInt32(address));
                    } else if (datatype.equals("UINT32")) {
                        ret = String.valueOf(s7.readUInt32(address));
                    } else if (datatype.equals("FLOAT")) {
                        ret = String.valueOf(s7.readFloat32(address));
                    } else if (datatype.equals("DOUBLE")) {
                        ret = String.valueOf(s7.readFloat64(address));
                    } else {
                        ret = "null";
                    }
                    client.publish(topic_send, ret.getBytes(), 1, false);
                }finally {
                    s7.close();
                }

            } else if (str[0].equals("set")) {
//                String url = str[1];
//                String tagaddress = str[2];
//                String value = String.valueOf(dataMap.get("params"));
//                try (PlcConnection connection = new DefaultPlcDriverManager().getConnection(url)) {
//                    final PlcWriteRequest.Builder writeBuilder = connection.writeRequestBuilder();
//                    writeBuilder.addTagAddress("tag1", tagaddress, value);
//                    final PlcWriteRequest writeRequest = writeBuilder.build();
//                    final PlcWriteResponse writeResponse = writeRequest.execute().get(5, TimeUnit.SECONDS);
//
//                    if (writeResponse.getResponseCode("tag1") == PlcResponseCode.OK) {
//                        System.out.println("        - Write OK");
//                        client.publish(topic_send, value.getBytes(), 1, false);
//                    }
//                }catch (Exception e){
//                    client.publish(topic_send, "0".getBytes(), 1, false);
//                }

                String plctype = str[1];
                String ip = str[2];
                String address = str[3];
                String datatype = str[4];

                String params = dataMap.get("params");

                log.info("{} {} {} {}",plctype,ip,address,datatype);

                String ret;
                //S200_SMART
                S7PLC s7 = new S7PLC(EPlcType.valueOf(plctype),ip);
                try {
                    if (datatype.equals("BOOL")) {
                        s7.writeBoolean(address,Boolean.parseBoolean(params));
                    } else if (datatype.equals("BYTE")) {
                        s7.writeByte(address,Byte.parseByte(params));
                    } else if (datatype.equals("INT16")) {
                        s7.writeInt16(address,Short.parseShort(params));
                    } else if (datatype.equals("UINT16")) {
                        s7.writeUInt16(address,Integer.parseInt(params));
                    } else if (datatype.equals("INT32")) {
                        s7.writeInt32(address,Integer.parseInt(params));
                    } else if (datatype.equals("UINT32")) {
                        s7.writeUInt32(address,Long.parseLong(params));
                    } else if (datatype.equals("FLOAT")) {
                        s7.writeFloat32(address,Float.parseFloat(params));
                    } else if (datatype.equals("DOUBLE")) {
                        s7.writeFloat64(address,Double.parseDouble(params));
                    } else {
                        return ;
                    }
                    client.publish(topic_send, "0".getBytes(), 1, false);
                }finally {
                    s7.close();
                }
            }else{
                client.publish(topic_send, "null".getBytes(), 1, false);
            }


        }
    }

    /**
     * 消息发布成功的回调
     */
    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        IMqttAsyncClient client = token.getClient();
        System.out.println(client.getClientId() + "发布消息成功！");

    }

}